package airacrobats.io;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * This base class loads objects from the resource files.
 */
public abstract class Loader<T>
{
    /**
     * The objects loaded.
     */
    private Map<String, T> objects;
    /**
     * An ordered list of the loaded objects.
     */
    private List<T> objectsList;

    /**
     */
    public Loader()
    {
        objects = new HashMap<String, T>();
        objectsList = new ArrayList<T>();
    }

    /**
     * @return A collection with all the objects.
     */
    public Collection<T> getObjects()
    {
        return objectsList;
    }

    /**
     * @return Amount of objects loaded.
     */
    public int getCount()
    {
        return objects.size();
    }

    /**
     * @param key The mapped key of the object.
     * @return The object.
     */
    public T get(String key)
    {
        return objects.get(key);
    }

    /**
     * Starts loading the resources.
     * @param files A map with all files (with its respective map keys).
     * @param loaderListener The listener notified when the loader finishes its work.
     * @param increment The amount to increment on the loading progress.
     * @param message The message of the loading event.
     * @param multiple Flag indicating if each file has multiple objects.
     */
    public void startLoading(final Map<String, String> files, final LoaderListener loaderListener,
            final double increment, final String message, final boolean multiple)
    {
        Thread t = new Thread()
        {
            @Override
            public void run()
            {
                Exception exception = null;
 
                try
                {
                    // On this case, each file contains one object.
                    for (Map.Entry<String, String> entry : files.entrySet())
                    {
                        String file = entry.getValue();
                        if (!multiple)
                        {
                            T t = load(file);
                            objects.put(entry.getKey(), t);
                            objectsList.add(t);
                        }
                        else
                        {
                            // On this case, many objects will be extracted from the resource.
                            int index = 0;
                            T t;
                            while ((t = load(file)) != null)
                            {
                                objects.put(entry.getKey() + "_" + index++, t);
                                objectsList.add(t);
                            }
                        }
                    }      
                }
                catch (Exception ex)
                {
                    exception = ex;
                }
                finally
                {
                    loaderListener.loadFinished(exception, Loader.this, increment, message);
                }
            }
        };

        t.start();
    }

    /**
     * Loads the file.
     * @param file The file to be loaded.
     * @return The object loaded.
     * @throws Exception Thrown if an error occurs.
     */
    protected abstract T load(String file) throws Exception;
}
